#ifndef FREE_LIST_H
#define FREE_LIST_H

#include "cpl_port.h"
#include <string>

class TABBinBlockManager;

#define  IDT_FILE_MAGIC '\0TDI' 

class TABIDTFileIndexEntry
{
public:
    GInt32 m_nBlockAddress;
    GInt32 m_nIndexPtr;
    GInt32 m_pad[2];
};

class TABIDTFileIndex
{
public:
    TABIDTFileIndex();
    ~TABIDTFileIndex();

    bool    Open(const char * pszFname);
    void    Close();
    int     Flush();
    int     Destory();
    int     IsFileReadOnly();

    GInt32  GetBlockPtr(GInt32 nBlockAddress);
    void    SetBlockPtr(GInt32 nBlockAddress, GInt32 nBlockPtr);

private:
    char* m_pszFname;
    FILE * m_fpIndex;
};




class TABIDTFileEntry       // 32 bytes per entry
{
public:
    GBool  m_bIsDeleted;

    GInt32 m_blockOffset;

    // The offset of the free space in map file, 0 means this entry in not used
    GInt32 m_offsetInMapFile;

    // Size of the free space
    GInt32 m_szFreeSpace;

    // the next space in the same block, 0 for last one
    GInt32 m_nextFreeSpaceInBlock;

    // the prev space in the same block, 0 for first one
    GInt32 m_prevFreeSpaceInBlock;

    GInt32 m_pad[2];
};

class TABIDTFileHeader
{
public:
    GInt32 m_magic;
    GInt32 m_tTimeStamp;
    GInt32 m_pad[6];
};


/************************************************************************/
/* Temporary Index File                                                 */
/************************************************************************/
class TABIDTFile
{
public:
    TABIDTFile();
    ~TABIDTFile();

    bool                Open(const char * pszFname);
    void                Close(GInt32 m_tTimeStamp = 0);
    int                 Flush(GInt32 m_tTimeStamp = 0);
    int                 Destory();
    int                 IsFileReadOnly();
    GInt32              Allocate(GInt32 size);
    bool                Free(FILE * fpMap, 
                             GInt32 nBlockAddress, 
                             GInt32 offsetInMapFile, 
                             GInt32 size, 
                             TABBinBlockManager * pBlockManager);

protected:
    bool                GetEntry(GInt32 offset, TABIDTFileEntry * pEntry);
    bool                SetEntry(GInt32 offset, TABIDTFileEntry * pEntry);
    void                DeleteEntry(GInt32 nEntryPtr);
    GInt32              GetNextBlock(GInt32 nBlockAddress, FILE * fpMap);

private:
    // Time stamp of the corresponding MAP file. This is used to indicate
    // whether the index file is uptodate/
    TABIDTFileHeader m_header;
    char* m_pszFname;
    FILE* m_fpIDT;

    TABIDTFileIndex m_fileIndex;

};
#endif
